package cn.devcat.sso.service.impl;

import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

import javax.annotation.Resource;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;

import cn.devcat.sso.config.exception.DevcatRoleException;
import cn.devcat.sso.entity.DevcatRole;
import cn.devcat.sso.entity.PageData;
import cn.devcat.sso.entity.SearchCommonParam;
import cn.devcat.sso.mapper.DevcatRoleMapper;
import cn.devcat.sso.service.IDevcatRoleService;
import cn.devcat.sso.util.PageHelperUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class DevcatRoleServiceImpl extends ServiceImpl<DevcatRoleMapper, DevcatRole> implements IDevcatRoleService {

	@Resource
	DevcatRoleMapper roleMapper;

	/**
	 * 通过用户ID获取角色嘻嘻
	 */
	@Cacheable(cacheNames="roleListByUserId", key="#userId")
	@Override
	public List<DevcatRole> getRoleListByUserId(String userId) {
    List<DevcatRole> roleListByUserId = roleMapper.getRoleListByUserId(userId);
    Optional<DevcatRole> max = roleListByUserId.stream().max(Comparator.comparingInt(DevcatRole::getRoleWeight));
    if (max.isPresent()) {
      DevcatRole maxWeightRole = max.get();
      return list(new QueryWrapper<DevcatRole>().le("role_weight", maxWeightRole.getRoleWeight()));
    }
    return roleListByUserId;
	}

	/**
	 * 新增角色
	 * @throws DevcatRoleException
	 */
	@CacheEvict(cacheNames = {"roleListByApiPatternId","roleListByUserId"}, allEntries = true)
	@Override
	public void addDevcatRole(DevcatRole role) {
		if(StringUtils.isEmpty(role.getRoleCode()) || StringUtils.isEmpty(role.getRoleName())) {
			throw new DevcatRoleException("角色的名称或代号为空，添加失败");
		}
		checkIsSameRole(role);
		role.setCreateTime(LocalDateTime.now());
		save(role);
	}

	/**
	 * 删除角色
	 * @throws DevcatRoleException
	 */
	@CacheEvict(cacheNames = {"roleListByApiPatternId","roleListByUserId"}, allEntries = true)
	@Transactional
	@Override
	public void removeDevcatRole(List<String> ids) {
		if(ids == null || ids.isEmpty()) {
			throw new DevcatRoleException("删除的角色ID为空");
		}
		//删除角色前要将所有关联的表对应的角色ID也删除掉
		roleMapper.clearRoleRelationForUser(ids);
		roleMapper.clearRoleRelationForApiPattern(ids);
		removeByIds(ids);
		log.info("remove role successful");
	}

	/**
	 * 更新角色信息
	 * @throws DevcatRoleException
	 */
	@CacheEvict(cacheNames = {"roleListByApiPatternId","roleListByUserId"}, allEntries = true)
	@Override
	public void updateDevcatRole(DevcatRole role) {
		if(StringUtils.isEmpty(role.getId())) {
			throw new DevcatRoleException("更新的角色缺少ID参数");
		}
		checkIsSameRole(role);
		updateById(role);
	}


	@Override
	public PageData<DevcatRole> listDevcatRole(SearchCommonParam param) {
		QueryWrapper<DevcatRole> queryWrapper = new QueryWrapper<>();
		if(StringUtils.isNotEmpty(param.getKeyword())) {
			queryWrapper.like("role_code", param.getKeyword()).or().like("role_name", param.getKeyword());
		}
		queryWrapper.orderByDesc("create_time");
		PageHelperUtil.handle(param);
		List<DevcatRole> list = list(queryWrapper);
		return PageHelperUtil.makePageData(new PageInfo<>(list));
	}


	@Cacheable(cacheNames = "roleListByApiPatternId", key = "#apiPatternId")
	@Override
	public List<DevcatRole> getRoleListByApiPatternId(String apiPatternId) {
		return roleMapper.getRoleListByApiPatternId(apiPatternId);
	}


	/**
	 * 检查是否有相同的角色代号
	 * @param role 当前角色
	 * @throws DevcatRoleException
	 */
	private void checkIsSameRole(DevcatRole role) {
		QueryWrapper<DevcatRole> queryWrappre = new QueryWrapper<>();
		queryWrappre.eq("role_code", role.getRoleCode());
		if(role.getId()!=null) {
			queryWrappre.ne("id", role.getId());
		}
		long count = count(queryWrappre);
		if(count > 0) {
			throw new DevcatRoleException("角色代号"+role.getRoleCode()+"已经存在");
		}
	}


}
